package fr.unice.polytech.chord.gui;

import java.util.HashMap;
import java.util.Map;

import org.objectweb.proactive.api.PAFuture;

import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.SparseMultigraph;
import fr.unice.polytech.chord.core.ChordNode;

/**
 * Display the Overlay in {@link ChordVisualizer} by using the Jung library.
 * 
 * @author Anthony Parisy
 * @author Laurent Pellegrino
 * @author Marc Valdener
 * 
 * @version 06/11/2009
 */
public class ChordDisplayer {

	public static int REFRESH_TIME = 1000;

	private Graph<Integer, String> graph;
	private Map<Integer, ChordNode> nodes;
	private ChordNode selectedNode;

	private ChordVisualizer gui;

	public ChordDisplayer(ChordVisualizer gui) {
		this.gui = gui;
		this.nodes = new HashMap<Integer, ChordNode>();
		this.graph = new SparseMultigraph<Integer, String>();
		this.selectedNode = this.gui.getTracker().getRandomPeer();

		this.fillGraph(this.graph, this.selectedNode);

		// Refreshing Thread
		Thread refreshThread = new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					try {
						Thread.sleep(ChordDisplayer.REFRESH_TIME);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					updateGraph(ChordDisplayer.this.gui.getTracker()
							.getRandomPeer());
				}
			}
		});
		refreshThread.start();
	}

	public void updateGraph(ChordNode overlay) {
		try {
			if (overlay != null) {
				for (Integer i : nodes.keySet()) {
					graph.removeVertex(i);
				}
				this.nodes.clear();
				this.fillGraph(graph, overlay);

				this.gui.updateGraph();
			}
		} catch (Exception e) {
			// do nothing wait for stabilization
		}
	}

	public void fillGraph(Graph<Integer, String> g, ChordNode overlay) {
		if (PAFuture.getFutureValue(overlay) != null) {
			int debut = overlay.getKey().getValue().intValue();
			g.addVertex(debut);
			this.nodes.put(debut, overlay);
			overlay = overlay.getSuccessor();
			int first = debut;
			int next = overlay.getKey().getValue().intValue();
			while (debut != next) {
				g.addVertex(next);
				g.addEdge("Egde" + first + "->" + next, first, next);
				this.nodes.put(next, overlay);
				overlay = overlay.getSuccessor();
				if (overlay == null) {
					break;
				} else {
					first = next;
					next = overlay.getKey().getValue().intValue();
				}
			}
			g.addEdge("Egde" + first + "->" + next, first, next);
		}
	}

	public Graph<Integer, String> getGraph() {
		return graph;
	}

	public Map<Integer, ChordNode> getNodes() {
		return nodes;
	}

	public void setGraph(Graph<Integer, String> graph) {
		this.graph = graph;
	}

	public void setNodes(Map<Integer, ChordNode> nodes) {
		this.nodes = nodes;
	}
}
